/**
  ******************************************************************************
  * @author     Chris
  * @since      2024/6/13 14:27
  *
  * @file       pd_timer_oc.c
  * @brief      TimerOC peripheral driver.
  *
  * @note       This file contains the peripheral driver for the TimerOC.
  *
  * @warning    None.
  ******************************************************************************
  * Change Logs:
  *   Date          Author       Notes
  *   2024/6/13     Chris        the first version
  *
  ******************************************************************************
  */

#include <stm32f4xx_ll_tim.h>
#include "pd_timer_oc.h"

static void TimerOC_init_(const TimerOC *this) {
    LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};

    LL_TIM_OC_StructInit(&TIM_OC_InitStruct);
    TIM_OC_InitStruct.OCMode       = this->OCMode;
    TIM_OC_InitStruct.OCPolarity   = this->OCPolarity;
    TIM_OC_InitStruct.OCState      = this->OCState;
    TIM_OC_InitStruct.CompareValue = this->CompareValue;

    const uint32_t *channel = this->timerCh->channels;
    for (int i = 0; i < this->timerCh->chSize; ++i) {
        LL_TIM_OC_Init(this->timer->TIMx, channel[i], &TIM_OC_InitStruct);
    }

    // GPIO init
    TimerCh_init(this->timerCh);
}

static void TimerOC_setCCR_(const TimerOC *this, uint32_t channel, uint32_t compareValue) {
    switch (channel) {
        case LL_TIM_CHANNEL_CH1: LL_TIM_OC_SetCompareCH1(this->timer->TIMx, compareValue);
            break;
        case LL_TIM_CHANNEL_CH2: LL_TIM_OC_SetCompareCH2(this->timer->TIMx, compareValue);
            break;
        case LL_TIM_CHANNEL_CH3: LL_TIM_OC_SetCompareCH3(this->timer->TIMx, compareValue);
            break;
        case LL_TIM_CHANNEL_CH4: LL_TIM_OC_SetCompareCH4(this->timer->TIMx, compareValue);
            break;
        default: break;
    }
}

void TimerOC_constructor(TimerOC *this, Timer *timer, TimerCh *timerCh, uint32_t compareValue) {
    static struct TimerOCVtbl vtbl = {
        .init = &TimerOC_init_,
        .set_ccr = &TimerOC_setCCR_,
    };

    this->vptr = &vtbl;
    this->timer = timer;
    this->timerCh = timerCh;

    this->OCMode       = LL_TIM_OCMODE_PWM1;
    this->OCPolarity   = LL_TIM_OCPOLARITY_HIGH;
    this->OCState      = LL_TIM_OCSTATE_ENABLE;
    this->CompareValue = compareValue;
}
